package dkbta.ontology.values;

import dkbta.ontology.Ontology;
import dkbta.ontology.elements.Element;
import dkbta.ontology.elements.ElementType;
import dkbta.ontology.elements.event.Event;
import dkbta.ontology.elements.event.EventAttribute;
import dkbta.ontology.elements.event.EventDef;
import dkbta.ontology.loading.OntologyException;

/**
 * A value condition that operates on the value of an event's attribute
 * 
 * @author Uri Kanonov
 */
public class AttributeValueCondition extends ValueCondition{
	/** The attribute name of the given event the constraint refers to */
	private final String _attributeName;

	/**
	 * Constructs an event based constraint with the given event and attribute name
	 * 
	 * @param eventName The name of the element the constraint is based on
	 * @param attributeName The attribute name of the given event the constraint refers to
	 * @param possibleValues The possible values the constraint allows
	 */
	public AttributeValueCondition(String eventName, String attributeName,
		Values possibleValues){
		super(eventName, ElementType.EVENT, possibleValues);
		_attributeName = attributeName;
	}

	/**
	 * Returns the attribute name of the given event the constraint refers to
	 * 
	 * @return The attribute name of the given event the constraint refers to
	 */
	public String getAttributeName(){
		return _attributeName;
	}

	@Override
	public void validate(Ontology ontology) throws OntologyException{
		EventDef event = ontology.getEvent(_elementName);
		if (event == null){
			throw new OntologyException(
					"The value constraint operates on a non-existing event: "
							+ _elementName);
		}
		ScaledValues attrScaledValues = event.getAttributeValues(_attributeName);
		if (attrScaledValues == null){
			throw new OntologyException(
					"The value constraint operates on a non-existing attribute "
							+ _attributeName + " of " + _elementName);
		}

		// Making sure the constraint's value type and the attribute's value type
		// match
		Values attrValues = attrScaledValues.getValues();
		ValuesType attributeValType = attrValues.getValueType();
		ValuesType constraintValType = _allowedValues.getValueType();

		if (attributeValType != constraintValType){
			throw new OntologyException("Value constraint of type " + constraintValType
					+ " on the attribute " + _attributeName + " of " + _elementName
					+ " with value type " + attributeValType);
		}
		if (!attrValues.contains(_allowedValues)){
			throw new OntologyException("The constraint's values '" + _allowedValues
					+ "' are not contained in the values of the attribute "
					+ _attributeName + " of " + _elementName + " '" + attrValues + "'");
		}
	}

	@Override
	public String toString(){
		StringBuilder sb = new StringBuilder();
		sb.append("Event - ").append(_elementName);
		sb.append(" [");
		sb.append(_attributeName);
		sb.append("], ");
		sb.append(_allowedValues);
		return sb.toString();
	}


	@Override
	public boolean checkCondition(Element e){
		EventAttribute evAttrInst = ((Event)e).getAttribute(getAttributeName());
		return _allowedValues.isValid(evAttrInst.getValueType(), evAttrInst.getValue());
	}

}
